use crate::field::VddFieldRef;
use crate::{to_sha256_hash, Astr, FieldId, RecordId};
use serde_json::Value;
use std::collections::HashMap;
use std::sync::Arc;

pub const C_TT_ANO: u8 = 0;
pub const C_TT_PK: u8 = 1;
pub const C_TT_ACC: u8 = 2;
pub const C_TT_VC: u8 = 3;

#[derive(Debug)]
pub struct ClientToken {
    pub token_type: u8,
    pub salt: Option<u32>,
    pub hash: Option<Astr>,
}

impl ClientToken {
    pub fn eq_hash(&self, s: &str) -> bool {
        // info!("{}", s);
        let hash = to_sha256_hash(s.as_bytes());
        let token_hash = self.hash.clone().unwrap();
        // tracing::info!("{}", hash);
        // tracing::info!("{}", token_hash);
        hash == token_hash
    }
}

/// 网关数据操作
#[derive(Debug)]
pub struct RecordAction {
    pub a: u8,                 // 操作代码
    pub rec_id: RecordId,      // 记录ID
    pub f_id: Option<FieldId>, // 字段ID
    pub v: Option<Value>,      // 其他参数
    pub idx: isize,
}

impl RecordAction {
    fn from_json(j: &Value, tags: &HashMap<Astr, VddFieldRef>) -> Result<RecordAction, Astr> {
        let action = j["action"].as_u64().unwrap_or(0) as u8;
        if action < 1 {
            return Err("无效操作代码".into());
        }
        let id = j["_id"].as_u64().unwrap();
        let id = RecordId(id);
        let tag = j["tag"].as_str().unwrap_or("");
        let field = tags.get(&Arc::from(tag));
        Ok(RecordAction {
            a: action,
            rec_id: id,
            f_id: field.map(|f| f.id.clone()),
            v: j.get("fv").cloned(),
            idx: j["idx"].as_i64().unwrap_or(-1) as isize,
        })
    }
    ///
    pub fn batch_from_json(
        j: &[Value],
        fields: &HashMap<Astr, VddFieldRef>,
    ) -> Result<Vec<RecordAction>, Astr> {
        let mut r: Vec<RecordAction> = Vec::new();
        for action in j.iter() {
            r.push(RecordAction::from_json(action, fields)?);
        }
        Ok(r)
    }
}
